﻿namespace Common.Unit
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public static class StringExtensions
    {

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int ToIntOrZero(this string str)
        {
            int value;
            if (!int.TryParse(str, out value))
                return 0;
            return value;
        }

        public static int ToIntOrMax(this string str)
        {
            int value;
            if (!int.TryParse(str, out value))
                return int.MaxValue;
            return value;
        }

        public static int ToIntOrMinus(this string str)
        {
            int value;
            if (!int.TryParse(str, out value))
                return -1;
            return value;
        }

        public static int ToIntOrOne(this string str)
        {
            int value;
            if (!int.TryParse(str, out value))
                return 1;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static short ToShortOrMinus(this string str)
        {
            short value;
            if (!short.TryParse(str, out value))
                return -1;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static short ToShortOrZero(this string str)
        {
            short value;
            if (!short.TryParse(str, out value))
                return 0;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int? ToIntOrNull(this string str)
        {
            int value;
            if (!int.TryParse(str, out value))
                return null;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static byte? ToByteOrNull(this string str)
        {
            byte value;
            if (!byte.TryParse(str, out value))
                return null;
            return value;
        }

        public static byte ToByteOrZero(this string str)
        {
            byte value;
            if (!byte.TryParse(str, out value))
                return 0;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static decimal ToDecimalOrZero(this string str)
        {
            decimal value;
            if (!decimal.TryParse(str, out value))
                return 0;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static decimal? ToDecimalOrNull(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return null;
            decimal value;
            if (!decimal.TryParse(str, out value))
                return null;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static decimal ToDecimalOrMinus(this string str)
        {
            decimal value;
            if (!decimal.TryParse(str, out value))
                return -1;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static short? ToShortOrNull(this string str)
        {
            short value;
            if (!short.TryParse(str, out value))
                return null;
            return value;
        }

        public static double ToDoubleOrZero(this string str)
        {
            double value;
            if (!double.TryParse(str, out value))
                return 0;
            return value;
        }

        public static double? ToDoubleOrNull(this string str)
        {
            double value;
            if (!double.TryParse(str, out value))
                return null;
            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool ToBool(this string str)
        {
            if(string.IsNullOrEmpty(str))
                return false;

            str = str.Trim().ToLower();
            string[] trueExpresses = new string[]{"1","on","yes","true","y","checked"};
            return trueExpresses.Contains(str);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool? ToBoolOrNull(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return null;
            return ToBool(str);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime? ToDateTimeOrNull(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return null;
            str = str.Trim();
            DateTime value = new DateTime();
            DateTime.TryParse(str, out value);
            if (!DateTime.TryParse(str, out value))
            {
                return null;
                //throw new ArgumentException("Invalid DateTime Format!");
            }
            return value;
        }

        /// <summary>
        /// 对于2010-12-28 的日期,返回2010-12-28 23:59:59
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime? ToBigDateTimeOrNull(this string str)
        {
            DateTime? value = ToDateTimeOrNull(str);
            if (value.HasValue)
            {
                return Convert.ToDateTime(value.Value.ToString("yyyy-MM-dd 23:59:59"));
            }
            return value;
        }

        public static DateTime? JsonToDateTime(this object jsonDate)
        {
            if (jsonDate == null)
                return null;
            return JsonToDateTime(jsonDate.ToString());
        }

        public static DateTime? JsonToDateTime(this string jsonDate)
        {
            if (string.IsNullOrEmpty(jsonDate))
                return null;
            jsonDate = jsonDate.Trim();
            DateTime timeValue = new DateTime();
            if (DateTime.TryParse(jsonDate, out timeValue))
                return timeValue;

            string value = jsonDate.Substring(6, jsonDate.Length - 8);
            DateTimeKind kind = DateTimeKind.Utc;
            int index = value.IndexOf('+', 1);
            if (index == -1)
                index = value.IndexOf('-', 1);
            if (index != -1)
            {
                kind = DateTimeKind.Local;
                value = value.Substring(0, index);
            }
            long javaScriptTicks = long.Parse(value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture);
            long InitialJavaScriptDateTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
            DateTime utcDateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks, DateTimeKind.Utc);
            DateTime dateTime;
            switch (kind)
            {
                case DateTimeKind.Unspecified:
                    dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
                    break;
                case DateTimeKind.Local:
                    dateTime = utcDateTime.ToLocalTime();
                    break;
                default:
                    dateTime = utcDateTime;
                    break;
            }
            return dateTime;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string str)
        {
            NullSafeCheck(str);
            str = str.Trim();
            DateTime value = new DateTime();
            if (!DateTime.TryParse(str, out value))
                throw new ArgumentException("Invalid DateTime Format!");
            return value;
        }

        /// <summary>
        /// 将字符串按逗号分隔成字符串数组输出
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string[] ToArray(this string str)
        {
            return str.ToArray(',', true);
        }
        
        
        /// <summary>
        /// 将字符串按指定分隔符分隔成字符串数组输出
        /// </summary>
        /// <param name="str"></param>
        /// <param name="separator">分隔符</param>
        /// <returns></returns>
        public static string[] ToArray(this string str, char separator)
        {
            return str.ToArray(separator, true);
        }

        public static string[] ToArrayOrNull(this string str)
        {
            string[] strArray = null;
            try
            {
                strArray = str.ToArray();
            }
            catch { }
            return strArray;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <param name="separator"></param>
        /// <param name="trimSeparator">是否去年开头和结尾的分隔符</param>
        /// <returns></returns>
        public static string[] ToArray(this string str, char separator, bool trimSeparator)
        {
            NullSafeCheck(str);
            str = str.Trim();
            if (trimSeparator)
            {
                str = str.Trim(separator);
                //如果出现相连的分隔符
                string dblSep = new string(new char[] { separator, separator });
                while(str.Contains(dblSep))
                {
                    str = str.Replace(dblSep, separator.ToString());
                }
            }
            if (str.Contains(separator.ToString()))
                return str.Split(separator);
            else
                return new string[1] { str };
        }

        /// <summary>
        /// 将字符串按逗号分隔转换成字符串整形数组输出
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int[] ToIntArray(this string str)
        {
            return str.ToIntArray(',');
        }

        public static List<int> ToIntList(this string str)
        {
            return str.ToIntArray().ToList();
        }

        public static double[] ToDoubleArray(this string str)
        {
            return str.ToDoubleArray(',');
        }

        public static int[] ToIntArrayOrNull(this string str)
        {
            int[] intArray = null;
            try
            {
                intArray = str.ToIntArray();
            }
            catch { }
            return intArray;
        }

        /// <summary>
        /// 将字符串按分隔符分隔转换成字符串整形数组输出
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int[] ToIntArray(this string str, char separator)
        {
            NullSafeCheck(str);
            str = str.Trim().Trim(separator);
            if (str.Contains(separator.ToString()))
            {
                string[] strArray = str.Split(separator);
                int arrLength = strArray.Length;
                int[] targetTypeArray = new int[arrLength];

                for (int i = 0; i < arrLength;i++ )
                {
                    targetTypeArray[i] = strArray[i].ToIntOrMinus();
                }
                return targetTypeArray;
            }
            else
                return new int[1] { str.ToIntOrZero() };
        }

        public static double[] ToDoubleArray(this string str, char separator)
        {
            NullSafeCheck(str);
            str = str.Trim().Trim(separator);
            if (str.Contains(separator.ToString()))
            {
                string[] strArray = str.Split(separator);
                int arrLength = strArray.Length;
                double[] targetTypeArray = new double[arrLength];

                for (int i = 0; i < arrLength; i++)
                {
                    targetTypeArray[i] = strArray[i].ToDoubleOrZero();
                }
                return targetTypeArray;
            }
            else
                return new double[1] { str.ToIntOrZero() };
        }

        /// <summary>
        /// 将字符串按逗号分隔转换成字符串小数数组输出
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static decimal[] ToDecimalArray(this string str)
        {
            return str.ToDecimalArray(',');
        }

        /// <summary>
        /// 将字符串按逗号分隔符转换成字符串小数数组输出
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static decimal[] ToDecimalArray(this string str, char separator)
        {
            NullSafeCheck(str);
            str = str.Trim().Trim(separator);
            if (str.Contains(separator.ToString()))
            {
                string[] strArray = str.Split(separator);
                int arrLength = strArray.Length;
                decimal[] targetTypeArray = new decimal[arrLength];

                for (int i = 0; i < arrLength; i++)
                {
                    targetTypeArray[i] = strArray[i].ToDecimalOrMinus();
                }
                return targetTypeArray;
            }
            else
                return new decimal[1] { str.ToDecimalOrMinus() };
        }

        /// <summary>
        /// 使str满足 id in(str) 格式要求
        /// </summary>
        /// <param name="str"></param>
        public static string ToNotNullSafeSQLIds(this string str)
        {
            NullSafeCheck(str);
            str = str.Trim().Trim(',');
            NullSafeCheck(str);
            return str;
        }

        public static string ToNotNullSafeSQLGuids(this string str)
        {
            NullSafeCheck(str);
            str = "'" + str.Trim().Trim(',').Replace(",", "','") + "'";
            NullSafeCheck(str);
            return str;
        }

        public static string ToSafeSQLString(this string str)
        {
            str = str.Replace("'", "''");
            return str;
        }

        /// <summary>
        /// 使字符串可以用javascript正常输出
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ToJavaScriptString(this string str)
        {
            if (str == null || str.Length == 0)
                return string.Empty;
            return str.Replace("\r"," ").Replace("\n"," ");
        }

        private static void NullSafeCheck(string str)
        {
            if (str != null && str.Trim().Length > 0)
                return;
            throw new ArgumentException("Parameters cannot be none!");
        }

        /// <summary>
        /// 输出成文件大小
        /// </summary>
        /// <param name="fileSizeStr"></param>
        /// <returns></returns>
        public static string ToFileSizeString(this string fileSizeStr)
        {
            string fmtFileSize = string.Empty;
            long fileSize = fileSizeStr.ToLongOrZero();
            if (fileSize > 0)
            {
                string[] units = new string[] { "  Bytes ", "  KB ", "  MB ", "  GB ", "  TB ", "  PB ", "  EB ", "  ZB ", "  YB " };
                int uindex = 0;
                fmtFileSize = Math.Round(fileSize / Math.Pow(1024, (uindex = (int)Math.Floor(Math.Log(fileSize, 1024)))), 2) + units[uindex];
            }
            return fmtFileSize;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static Guid ToGuidOrEmpty(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return Guid.Empty;
            Guid value;
            if (!Guid.TryParse(str, out value))
                return Guid.Empty;
            return value;
        }

        public static Guid? ToGuidOrNull(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return null;
            Guid value;
            if (!Guid.TryParse(str, out value))
                return null;
            return value;
        }
    }
}
